package com.web.exiaodao.remote.service.impl;

import com.alibaba.fastjson.JSON;
import com.web.exiaodao.business.constant.JConstant;
import com.web.exiaodao.business.entity.FavoriteTable;
import com.web.exiaodao.business.entity.TravelTable;
import com.web.exiaodao.business.repository.FavoriteTableRepository;
import com.web.exiaodao.business.repository.TravelTableRepository;
import com.web.exiaodao.remote.service.ApiTravelTableService;
import com.web.exiaodao.remote.vo.CommentVo;
import com.web.exiaodao.remote.vo.TravelTableVo;
import com.web.exiaodao.remote.vo.UserVo;
import com.web.webstart.base.constant.XaConstant;
import com.web.webstart.base.exception.BusinessException;
import com.web.webstart.base.service.impl.BaseService;
import com.web.webstart.base.util.LocationUtils;
import com.web.webstart.base.util.XaUtil;
import com.web.webstart.base.util.jpa.DynamicSpecifications;
import com.web.webstart.base.util.jpa.MyPage;
import com.web.webstart.base.util.jpa.SearchFilter;
import com.web.webstart.base.util.jpa.SearchFilter.Operator;
import com.web.webstart.base.util.result.XaResult;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: zhangl
 * @times: 2016-11-02 15:02:37
 * 类的说明：前端APITravelTable接口实现类
 **/
@Service("ApiTravelTableService")
@Transactional(readOnly = false)
public class ApiTravelTableServiceImpl extends BaseService<TravelTable> implements ApiTravelTableService{

	private static final Logger LOGGER = Logger.getLogger(ApiTravelTableServiceImpl.class);
	private final double EARTH_RADIUS = 6371229; //地球的半径

	@Autowired
	TravelTableRepository travelTableRepository;
	@Autowired
	FavoriteTableRepository favoriteTableRepository;
	
	@Override
	public XaResult<TravelTableVo> findOne(Long tId) throws BusinessException {
		TravelTable obj = travelTableRepository.findByIdAndStatusNot(tId,XaConstant.Status.delete);
		XaResult<TravelTableVo> xr = new XaResult<TravelTableVo>();
		if (XaUtil.isNotEmpty(obj)) {
			xr.setObject(JSON.parseObject(JSON.toJSONString(obj),TravelTableVo.class));
			xr.getObject().setId(obj.getId());
			LOGGER.info("查询单个实体----->TravelTable");
		} else {
			xr.error(XaConstant.Message.object_not_find);
			LOGGER.info(XaConstant.Message.object_not_find);
			throw new BusinessException(XaConstant.Message.object_not_find);
		}
		return xr;
	}

	@Override
	public XaResult<TravelTableVo> findLastOne() throws BusinessException {
		XaResult<TravelTableVo> xr = new XaResult<>();
		Map<String, SearchFilter> filters = new HashMap<>();
			filters.put("status", new SearchFilter("status", Operator.NE, XaConstant.Status.delete));
			List<TravelTable> entitys = travelTableRepository.findAll(DynamicSpecifications
				.bySearchFilter(filters.values(), TravelTable.class), new Sort(
				new Sort.Order[]{
				new Sort.Order(Sort.Direction.DESC, "createTime"),
				new Sort.Order(Sort.Direction.DESC, "id")
				}));
				if (entitys == null || entitys.size() == 0) {
				xr.error("暂无信息");
				} else {
				xr.setObject(JSON.parseObject(JSON.toJSONString(entitys.get(0)), TravelTableVo.class));
				xr.getObject().setId(entitys.get(0).getId());
				LOGGER.info("查询单个实体----->TravelTable");
			}
		return xr;
	}

	@Override
	public XaResult<List<TravelTableVo>> findListNEStatusByFilter(
			Integer status, Map<String, Object> filterParams, Pageable pageable)
			throws BusinessException {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		if(status == null){// 默认显示非删除的所有数据
			status = XaConstant.Status.delete;
		}
		filters.put("status", new SearchFilter("status", Operator.NE, status));
		Page<TravelTable> page = travelTableRepository.findAll(DynamicSpecifications
				.bySearchFilter(filters.values(), TravelTable.class), pageable);
		XaResult<List<TravelTableVo>> xr = new XaResult<List<TravelTableVo>>();
		xr.setObject(JSON.parseArray(JSON.toJSONString(page.getContent()), TravelTableVo.class));
		for(int i=0;i<page.getContent().size();i++){
			xr.getObject().get(i).setId(page.getContent().get(i).getId());
		}
		return xr;
	}

	@Override
	public XaResult<List<TravelTableVo>> findListEQStatusByFilter(
			Integer status, Map<String, Object> filterParams, Pageable pageable)
			throws BusinessException {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		if(status == null){// 默认显示正常数据
			status = XaConstant.Status.valid;
		}
		filters.put("status", new SearchFilter("status", Operator.EQ, status));
		Page<TravelTable> page = travelTableRepository.findAll(DynamicSpecifications
				.bySearchFilter(filters.values(), TravelTable.class), pageable);
		XaResult<List<TravelTableVo>> xr = new XaResult<List<TravelTableVo>>();
		xr.setObject(JSON.parseArray(JSON.toJSONString(page.getContent()), TravelTableVo.class));
		for(int i=0;i<page.getContent().size();i++){
			xr.getObject().get(i).setId(page.getContent().get(i).getId());
		}
		return xr;
	}

	@Override
	public XaResult<TravelTableVo> multiOperate(String modelIds,
			Integer status) throws BusinessException {
		XaResult<TravelTableVo> xr = new XaResult<TravelTableVo>();
		if(status == null){
			status = XaConstant.Status.delete;
		}
		if(modelIds != null){
			String[] ids = modelIds.split(",");
			for(String id : ids){
				TravelTable obj = travelTableRepository.findByIdAndStatusNot(Long.parseLong(id),status);
				if (XaUtil.isNotEmpty(obj)) {
					obj.setStatus(status);
					obj = travelTableRepository.save(obj);
					xr.setObject(JSON.parseObject(JSON.toJSONString(obj), TravelTableVo.class));
					xr.getObject().setId(obj.getId());
				}
			}
		}
		LOGGER.info("更改数据状态----->TravelTable");
		return xr;
	}

	@Override
	public XaResult<TravelTableVo> createModel(TravelTable model)
			throws BusinessException {
		XaResult<TravelTableVo> xr = new XaResult<TravelTableVo>();
		TravelTable obj = travelTableRepository.save(model);
		xr.setObject(JSON.parseObject(JSON.toJSONString(obj), TravelTableVo.class));
		xr.getObject().setId(obj.getId());
		LOGGER.info("新增数据成功----->TravelTable");
		return xr;
	}

	@Override
	public XaResult<TravelTableVo> updateModel(TravelTable model)
			throws BusinessException {
		TravelTable obj = travelTableRepository.findOne(model.getId());
		XaResult<TravelTableVo> xr = new XaResult<TravelTableVo>();
		if (XaUtil.isNotEmpty(obj)) {
					obj.setTravelItemName(XaUtil.isNotEmpty(model.getTravelItemName()) ? model.getTravelItemName() : obj.getTravelItemName());
					obj.setTravelBrief(XaUtil.isNotEmpty(model.getTravelBrief()) ? model.getTravelBrief() : obj.getTravelBrief());
					obj.setTravelItemPrice(XaUtil.isNotEmpty(model.getTravelItemPrice()) ? model.getTravelItemPrice() : obj.getTravelItemPrice());
					obj.setTravelItemAddress(XaUtil.isNotEmpty(model.getTravelItemAddress()) ? model.getTravelItemAddress() : obj.getTravelItemAddress());
					obj.setLng(XaUtil.isNotEmpty(model.getLng()) ? model.getLng() : obj.getLng());
					obj.setLat(XaUtil.isNotEmpty(model.getLat()) ? model.getLat() : obj.getLat());
					obj.setTravelItemTelephone(XaUtil.isNotEmpty(model.getTravelItemTelephone()) ? model.getTravelItemTelephone() : obj.getTravelItemTelephone());
					obj.setTravelItemType(XaUtil.isNotEmpty(model.getTravelItemType()) ? model.getTravelItemType() : obj.getTravelItemType());
					obj.setRoute(XaUtil.isNotEmpty(model.getRoute()) ? model.getRoute() : obj.getRoute());
					obj.setCost(XaUtil.isNotEmpty(model.getCost()) ? model.getCost() : obj.getCost());
					obj.setSlogan(XaUtil.isNotEmpty(model.getSlogan()) ? model.getSlogan() : obj.getSlogan());
				obj = travelTableRepository.save(obj);
			xr.setObject(JSON.parseObject(JSON.toJSONString(obj), TravelTableVo.class));
			xr.getObject().setId(obj.getId());
		} else {
			xr.error(XaConstant.Message.object_not_find);
		}
		LOGGER.info("编辑数据成功----->TravelTable");
		return xr;
	}

	/**
	 * 查询所有旅游表(游学)
	 */
	@Override
	public XaResult<Page<TravelTableVo>> findTravelTableList(Double lat2,Double lng2,Pageable pageable,TravelTableVo travelTableVo)
			throws BusinessException {
//		SELECT t.id,b.picurl,t.travel_item_name,t.slogan,t.lng,t.lat,t.travel_item_price,t.travel_item_address,t.travel_brief,t.route,t.cost 
//		FROM `tb_xa_traveltable` t LEFT JOIN `tb_xa_banner` b ON t.id = b.object_id WHERE b.type = 2
		XaResult<Page<TravelTableVo>> xr=new XaResult<Page<TravelTableVo>>();
		StringBuffer sql = new StringBuffer("SELECT t.id,b.`picurl`,t.travel_item_name,t.slogan,t.lng,t.lat,t.travel_item_price,t.travel_item_address,t.travel_brief,t.route,t.cost," +
				"t.`travel_item_type`,t.create_time,b.`intro`,t.`sort`,t.click_cont,t.min_group_people,t.plan_start_time,t.reservation_price ");
		sql.append("FROM `tb_xa_traveltable` t ");
		sql.append("LEFT JOIN `tb_xa_banner` b ON t.id = b.object_id WHERE b.type = ").append(JConstant.BannerType.TRAVEL).append(" ");
		sql.append(" AND t.status<>").append(XaConstant.Status.delete);
		sql.append(" AND b.status<>").append(XaConstant.Status.delete);
		StringBuffer sql1 = new StringBuffer("select count(*) ");
		sql1.append("FROM `tb_xa_traveltable` t ");
		sql1.append("LEFT JOIN `tb_xa_banner` b ON t.id = b.object_id WHERE b.type = ").append(JConstant.BannerType.TRAVEL).append(" ");
		sql1.append(" AND t.status<>").append(XaConstant.Status.delete);
		sql1.append(" AND b.status<>").append(XaConstant.Status.delete);
		//查询条件
		if(XaUtil.isNotEmpty(travelTableVo.getTravelItemType())){
			sql.append(" AND t.travel_item_type= ").append(travelTableVo.getTravelItemType()).append(" ");
			sql1.append(" AND t.travel_item_type= ").append(travelTableVo.getTravelItemType()).append(" ");
		}
		if(XaUtil.isNotEmpty(travelTableVo.getId())){
			sql.append(" AND t.id= ").append(travelTableVo.getId()).append(" ");
			sql1.append(" AND t.id= ").append(travelTableVo.getId()).append(" ");
		}
		sql.append("AND t.status<>").append(XaConstant.Status.delete).append(" ORDER BY t.sort ASC,t.click_cont DESC,t.create_time desc");
		sql1.append("AND t.status<>").append(XaConstant.Status.delete).append(" ORDER BY t.sort ASC,t.click_cont DESC,t.create_time desc");
		List<Object[]> objs = this.query(sql.toString(), pageable.getPageNumber()*pageable.getPageSize(), pageable.getPageSize());
		List<TravelTableVo> vos = new ArrayList<TravelTableVo>();
		for (int i = 0; i < objs.size(); i++) {
			Object[] obj = objs.get(i);
			TravelTableVo vo = new TravelTableVo();
			vo.setId(Long.valueOf(obj[0].toString()));
//			vo.setPicurl(XaUtil.isEmpty(obj[1])?"":obj[1].toString());//只取一个
			if (XaUtil.isNotEmpty(obj[1]) && obj[1].toString().contains(JConstant.SYMBOL_DOT)) {
				vo.setPicurl(obj[1].toString().split(JConstant.SYMBOL_DOT)[0]);
            }
			vo.setTravelItemName(XaUtil.isEmpty(obj[2])?"":obj[2].toString());
			vo.setSlogan(XaUtil.isEmpty(obj[3])?"":obj[3].toString());
			
			Double lat1 = XaUtil.isEmpty(obj[5])?0:Double.valueOf(objs.get(i)[5].toString());
			Double lng1 = XaUtil.isEmpty(obj[4])?0:Double.valueOf(objs.get(i)[4].toString());
			if(lat2==null || lng2==null ){
				vo.setDistance("");
			}else{
				NumberFormat   nf=new  DecimalFormat( "0.0 "); 
				double distance = 0;
				distance = LocationUtils.getDistance(lat1, lng1, lat2, lng2);
				distance = Double.parseDouble(nf.format(distance));
				if(distance >= 1000.0000){
					distance = Double.parseDouble(nf.format(distance/1000));
					vo.setDistance(String.valueOf(distance+"km"));
				}else{
					vo.setDistance(String.valueOf(distance+"m"));
				}
			}
			
			vo.setTravelItemPrice(XaUtil.isEmpty(obj[6])?0:Double.valueOf(obj[6].toString()));
			vo.setTravelItemAddress(XaUtil.isEmpty(obj[7])?"":obj[7].toString());
			vo.setTravelBrief(XaUtil.isEmpty(obj[8])?"":obj[8].toString());
			vo.setRoute(XaUtil.isEmpty(obj[9])?"":obj[9].toString());
			vo.setCost(XaUtil.isEmpty(obj[10])?"":obj[10].toString());
			vo.setTravelItemType(XaUtil.isEmpty(obj[11])?0:Integer.valueOf(obj[11].toString()));
			vo.setCreateTime(XaUtil.isEmpty(obj[12])?"":obj[12].toString());
			vo.setSort(XaUtil.isEmpty(obj[14])?0:Long.valueOf(obj[14].toString()));
			vo.setClickCont(XaUtil.isEmpty(obj[15])?0:Long.valueOf(obj[15].toString()));
			vo.setMinGroupPeople(XaUtil.isEmpty(obj[16])?0:Integer.valueOf(obj[16].toString()));
			vo.setPlanStartTime(XaUtil.isEmpty(obj[17])?"":obj[17].toString());
			vo.setReservationPrice(XaUtil.isEmpty(obj[18])?0:Double.valueOf(obj[18].toString()));
			vos.add(vo);
		}
		List<Object[]> obj1=this.query(sql1.toString(), null, null);
		int count=Integer.parseInt(obj1.get(0)+"");	
		Page<TravelTableVo> page= new MyPage<TravelTableVo>(pageable.getPageNumber(),pageable.getPageSize(),vos,count);
		xr.setObject(page);
		return xr;
	}

	/**
	 * 计算公式
	 * @param long1
	 * @param lat1
	 * @param long2
	 * @param lat2
	 * @return
	 */
	public double Distance(double long1, double lat1, double long2, double lat2) {  
	    double a, b, R;  
	    R = 6378137; // 地球半径  
	    lat1 = lat1 * Math.PI / 180.0;  
	    lat2 = lat2 * Math.PI / 180.0;  
	    DecimalFormat    df   = new DecimalFormat("######0.00");   
	    a = lat1 - lat2;  
	    b = (long1 - long2) * Math.PI / 180.0;  
	    double d;  
	    double sa2, sb2;  
	    sa2 = Math.sin(a / 2.0);  
	    sb2 = Math.sin(b / 2.0);  
	    d = 2  
	            * R  
	            * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1)  
	                    * Math.cos(lat2) * sb2 * sb2)); 
	    d = Double.valueOf(df.format(d));
	    return d;  
	}  
	
	/**
	 * 计算经纬度点对应正方形4个点的坐标
	 * @param longitude
	 * @param latitude
	 * @param distance
	 * @return
	 */
	public Map<String, double[]> returnLLSquarePoint(double longitude,double latitude, double distance) {

	    Map<String, double[]> squareMap = new HashMap<String, double[]>();

	    // 计算经度弧度,从弧度转换为角度
	    double dLongitude = 2 * (Math.asin(Math.sin(distance
	            / (2 * EARTH_RADIUS))
	            / Math.cos(Math.toRadians(latitude))));
	    dLongitude = Math.toDegrees(dLongitude);

	    // 计算纬度角度
	    double dLatitude = distance / EARTH_RADIUS;
	    dLatitude = Math.toDegrees(dLatitude);

	    // 正方形
	    double[] leftTopPoint = { latitude + dLatitude, longitude - dLongitude };
	    double[] rightTopPoint = { latitude + dLatitude, longitude + dLongitude };
	    double[] leftBottomPoint = { latitude - dLatitude, longitude - dLongitude };
	    double[] rightBottomPoint = { latitude - dLatitude, longitude + dLongitude };
	    
	    squareMap.put("leftTopPoint", leftTopPoint);
	    squareMap.put("rightTopPoint", rightTopPoint);
	    squareMap.put("leftBottomPoint", leftBottomPoint);
	    squareMap.put("rightBottomPoint", rightBottomPoint);
	    
	    return squareMap;
	}
	
	//游学详情
	@Override
	public XaResult<List<TravelTableVo>> findTravelTableById(
			Long userId,TravelTableVo travelTableVo) throws BusinessException {
		XaResult<List<TravelTableVo>> xr=new XaResult<List<TravelTableVo>>();
		StringBuffer sql = new StringBuffer("SELECT t.id,b.picurl,t.travel_item_name,t.slogan,t.lng,t.lat,t.travel_item_price,t.travel_item_address,t.travel_brief,t.route,t.cost,t.travel_item_type,t.create_time,t.travel_item_telephone,t.`sort`,t.click_cont,t.min_group_people,t.plan_start_time,t.reservation_price ");
		sql.append("FROM `tb_xa_traveltable` t LEFT JOIN `tb_xa_banner` b ON t.id = b.object_id WHERE b.type = ").append(JConstant.BannerType.TRAVEL).append(" ");
		sql.append(" AND t.id= ").append(travelTableVo.getId()).append(" ");
//		sql.append(" AND t.travel_item_type= ").append(travelTableVo.getTravelItemType()).append(" ");
		sql.append(" AND t.status<>").append(XaConstant.Status.delete).append(" ORDER BY t.create_time desc");
		//查询一条评论
		StringBuffer s1 = new StringBuffer("SELECT c.`id`,u.`photo`,u.`mobile`,c.`comment_content`,c.`comment_imgs`,c.`create_time` ");
		s1.append("FROM `tb_xa_comment` c LEFT JOIN `tb_xa_user` u ON u.`id` = c.`user_id` ");
		s1.append("WHERE c.comment_types =").append(JConstant.Order_CommentType.TOUR).append(" AND object_id = ").append(travelTableVo.getId()).append(" AND c.STATUS<>").append(XaConstant.Status.delete);
		List<Object[]> objs1 = this.query(s1.toString(), null,null);
		CommentVo cVo = new CommentVo();
		UserVo uVo = new UserVo();
		if(XaUtil.isNotEmpty(objs1)){
			Object[] objarrs = objs1.get(0);
			cVo.setId(Long.valueOf(objarrs[0].toString()));
			uVo.setPhoto(XaUtil.isEmpty(objarrs[1])?"":objarrs[1].toString());
			uVo.setMobile(XaUtil.isEmpty(objarrs[2])?"":objarrs[2].toString());
			cVo.setComment_Content(XaUtil.isEmpty(objarrs[3])?"":objarrs[3].toString());
			cVo.setCommentImgs(XaUtil.isEmpty(objarrs[4])?"":objarrs[4].toString());
			cVo.setCreateTime(XaUtil.isEmpty(objarrs[5])?"":objarrs[5].toString());
			cVo.setUserVo(uVo);
		}
		
		List<Object[]> objs = this.query(sql.toString(), null,null);
		List<TravelTableVo> vos = new ArrayList<TravelTableVo>();
		TravelTableVo vo = new TravelTableVo();
		for (Object[] obj : objs) {
			vo.setId(Long.valueOf(obj[0].toString()));
			vo.setPicurl(XaUtil.isEmpty(obj[1])?"":obj[1].toString());
			vo.setTravelItemName(XaUtil.isEmpty(obj[2])?"":obj[2].toString());
			vo.setSlogan(XaUtil.isEmpty(obj[3])?"":obj[3].toString());
//			vo.setLng(XaUtil.isEmpty(obj[4])?0:Double.valueOf(obj[4].toString()));
//			vo.setLat(XaUtil.isEmpty(obj[5])?0:Double.valueOf(obj[5].toString()));
			vo.setTravelItemPrice(XaUtil.isEmpty(obj[6])?0:Double.valueOf(obj[6].toString()));
			vo.setTravelItemAddress(XaUtil.isEmpty(obj[7])?"":obj[7].toString());
			vo.setTravelBrief(XaUtil.isEmpty(obj[8])?"":obj[8].toString());
			vo.setRoute(XaUtil.isEmpty(obj[9])?"":obj[9].toString());
			vo.setCost(XaUtil.isEmpty(obj[10])?"":obj[10].toString());
			vo.setTravelItemType(XaUtil.isEmpty(obj[11])?0:Integer.valueOf(obj[11].toString()));
			vo.setCreateTime(XaUtil.isEmpty(obj[12])?"":obj[12].toString());
			vo.setTravelItemTelephone(XaUtil.isEmpty(obj[13])?"":obj[13].toString());
			vo.setSort(XaUtil.isEmpty(obj[14])?0:Long.valueOf(obj[14].toString()));
			vo.setClickCont(XaUtil.isEmpty(obj[15])?0:Long.valueOf(obj[15].toString()));
			vo.setMinGroupPeople(XaUtil.isEmpty(obj[16])?0:Integer.valueOf(obj[16].toString()));
			vo.setPlanStartTime(XaUtil.isEmpty(obj[17])?"":obj[17].toString());
			vo.setReservationPrice(XaUtil.isEmpty(obj[18])?0:Double.valueOf(obj[18].toString()));
		}
		//查看是否收藏
		FavoriteTable fobj = favoriteTableRepository.findByUserIdAndFavoriteObjectIdAndTypeAndStatusNot(userId, travelTableVo.getId().toString(), Integer.valueOf(JConstant.Search_Share_FavType.TOUR).toString(), XaConstant.Status.delete);
		if(XaUtil.isEmpty(fobj)){
			vo.setFavorite_State(false);
		}else{
			vo.setFavoriteId(fobj.getId());
			vo.setFavorite_State(fobj.getFavoriteState());
		}
		vo.setCommentVo(cVo);
		vos.add(vo);
		xr.setObject(vos);
		//点击量＋1 保存点击量
		TravelTable  o1 = travelTableRepository.findByIdAndStatusNot(travelTableVo.getId(), XaConstant.Status.delete);
		o1.setClickCont(1 + NumberUtils.toLong(o1.getClickCont()+""));
		travelTableRepository.save(o1);
		//点击量＋1END
		return xr;
	}

}
